libobs_wrapper\data\properties/
mod.rs

1mod enums;
2mod macros;
3pub mod prop_impl;
4pub mod types;
5
6use std::ffi::CStr;
7
8use libobs::obs_properties;
9use macros::*;
10
11pub use enums::*;
12use num_traits::FromPrimitive;
13use types::*;
14
15use crate::{run_with_obs, runtime::ObsRuntime, unsafe_send::Sendable, utils::{ObsError, ObsString}};
16
17#[derive(Debug, Clone)]
18pub enum ObsProperty {
19    /// A property that is not valid
20    Invalid(String),
21    /// A boolean property
22    Bool,
23    /// An integer property
24    Int(ObsNumberProperty<i32>),
25    /// A float property
26    Float(ObsNumberProperty<f64>),
27    /// A text property
28    Text(ObsTextProperty),
29    /// A path property
30    Path(ObsPathProperty),
31    /// A list property
32    List(ObsListProperty),
33    /// A color property
34    Color(ObsColorProperty),
35    /// A button property
36    Button(ObsButtonProperty),
37    /// A font property
38    Font(ObsFontProperty),
39    /// An editable list property
40    EditableList(ObsEditableListProperty),
41    /// A frame rate property
42    FrameRate(ObsFrameRateProperty),
43    /// A group property
44    Group(ObsGroupProperty),
45    /// A color alpha property
46    ColorAlpha(ObsColorAlphaProperty),
47}
48
49#[cfg_attr(not(feature = "blocking"), async_trait::async_trait)]
50pub trait ObsPropertyObjectPrivate {
51    #[cfg_attr(feature = "blocking", remove_async_await::remove_async_await)]
52    async fn get_properties_raw(&self) -> Result<Sendable<*mut libobs::obs_properties_t>, ObsError>;
53    #[cfg_attr(feature = "blocking", remove_async_await::remove_async_await)]
54    async fn get_properties_by_id_raw<T: Into<ObsString> + Sync + Send>(id: T, runtime: ObsRuntime) -> Result<Sendable<*mut libobs::obs_properties_t>, ObsError>;
55}
56
57#[cfg_attr(feature = "blocking", remove_async_await::remove_async_await)]
58async fn get_properties_inner(
59    properties_raw: Sendable<*mut obs_properties>,
60    runtime: ObsRuntime,
61) -> Result<Vec<ObsProperty>, ObsError> {
62    let properties_raw = properties_raw.clone();
63    if properties_raw.0.is_null() {
64        return Ok(vec![]);
65    }
66
67    run_with_obs!(runtime, (properties_raw), move || {
68        let mut result = Vec::new();
69        let mut property = unsafe { libobs::obs_properties_first(properties_raw) };
70        while !property.is_null() {
71            let name = unsafe { libobs::obs_property_name(property) };
72            let name = unsafe { CStr::from_ptr(name as _) };
73            let name = name.to_string_lossy().to_string();
74
75            let p_type = unsafe { libobs::obs_property_get_type(property) };
76            let p_type = ObsPropertyType::from_i32(p_type);
77
78            match p_type {
79                Some(p_type) => {
80                    result.push(p_type.to_property_struct(property));
81                }
82                None => result.push(ObsProperty::Invalid(name)),
83            }
84
85            // Move to the next property
86            unsafe { libobs::obs_property_next(&mut property) };
87        }
88
89        unsafe { libobs::obs_properties_destroy(properties_raw) };
90        result
91    }).await
92}
93
94/// This trait is implemented for all obs objects that can have properties
95#[cfg_attr(not(feature = "blocking"), async_trait::async_trait)]
96pub trait ObsPropertyObject: ObsPropertyObjectPrivate {
97    /// Returns the properties of the object
98    #[cfg_attr(feature = "blocking", remove_async_await::remove_async_await)]
99    async fn get_properties(&self) -> Result<Vec<ObsProperty>, ObsError>;
100
101    #[cfg_attr(feature = "blocking", remove_async_await::remove_async_await)]
102    async fn get_properties_by_id<T: Into<ObsString> + Sync + Send>(id: T, runtime: &ObsRuntime) -> Result<Vec<ObsProperty>, ObsError> {
103        let properties_raw = Self::get_properties_by_id_raw(id, runtime.clone()).await?;
104        get_properties_inner(properties_raw, runtime.clone()).await
105    }
106}